package search;

import java.io.IOException;

public class Intersections {

	private final int maxListMemorySize;

	public Intersections(int maxListMemorySize) {
		this.maxListMemorySize = maxListMemorySize;
	}

	public DiscBufferedIntegerList intersect(DiscBufferedIntegerList list1,
			DiscBufferedIntegerList list2) throws IOException {
		assert list1.getFileMgr().equals(list2.getFileMgr())
				& list1.getBufferMgr().equals(list2.getBufferMgr());
		DiscBufferedIntegerList res = new DiscBufferedIntegerList(list1
				.getFileMgr(), list1.getBufferMgr(), list1.getName() + " "
				+ list2.getName(), true, maxListMemorySize);
		list1.makeReadable();
		list2.makeReadable();
		int c1 = -1;
		int c2 = -2;
		while (list1.hasNext() & list2.hasNext()) {
			if (c1 > c2) {
				c2 = list2.readNext();
			}
			if (c2 > c1) {
				c1 = list1.readNext();
			}
			if (c1 == c2) {
				res.writeNext(c1);
				if(list1.hasNext()){
					c1=list1.readNext();
				}
				if(list2.hasNext()){
					c2=list2.readNext();
				}
			}
		}
		while(c1>c2&list2.hasNext()){
			c2=list2.readNext();
		}
		while(c2>c1&list1.hasNext()){
			c1=list1.readNext();
		}
		if(c1==c2){
			res.writeNext(c1);
		}
		list1.releaseAll();
		list2.releaseAll();
		return res;
	}

	public DiscBufferedIdWOList intersect(DiscBufferedIdWOList list1,
			DiscBufferedIdWOList list2) throws IOException {
		assert list1.getFileMgr().equals(list2.getFileMgr())
				& list1.getBufferMgr().equals(list2.getBufferMgr());
		DiscBufferedIdWOList res = new DiscBufferedIdWOList(list1.getFileMgr(),
				list1.getBufferMgr(), list1.getName() + " " + list2.getName(),
				true, maxListMemorySize);
		list1.makeReadable();
		list2.makeReadable();
		IdWithOccurences c1 = new IdWithOccurences();
		IdWithOccurences c2 = new IdWithOccurences();
		c1.id = -1;
		c2.id = -2;
		while (list1.hasNext() & list2.hasNext()) {
			if (c1.id > c2.id) {
				c2 = list2.readNext();
			}
			if (c2.id > c1.id) {
				c1 = list1.readNext();
			}
			if (c1.id == c2.id) {
				c1 = intersectOcc(c1, c2);
				if (c1.Occurences.size() > 0 | c1.isInMetaData) {
					res.writeNext(c1);
				}
				if(list1.hasNext()){
					c1=list1.readNext();
				}
				if(list2.hasNext()){
					c2=list2.readNext();
				}
			}
		}
		while(c1.id>c2.id&list2.hasNext()){
			c2=list2.readNext();
		}
		while(c2.id>c1.id&list1.hasNext()){
			c1=list1.readNext();
		}
		if(c1.id==c2.id){
			c1 = intersectOcc(c1, c2);
			if (c1.Occurences.size() > 0 | c1.isInMetaData) {
				res.writeNext(c1);
			}
		}
		list1.releaseAll();
		list2.releaseAll();
		return res;
	}

	private IdWithOccurences intersectOcc(IdWithOccurences occ1,
			IdWithOccurences occ2) {
		IdWithOccurences res = new IdWithOccurences();
		res.id = occ1.id;
		res.isInMetaData = occ1.isInMetaData & occ2.isInMetaData;
		while (occ1.Occurences.size() > 0 & occ2.Occurences.size() > 0) {
			if (occ1.Occurences.getFirst() + 1 == occ2.Occurences.getFirst()) {
				res.Occurences.addLast(occ2.Occurences.getFirst());
				occ1.Occurences.removeFirst();
				occ2.Occurences.removeFirst();
			} else {
				if (occ1.Occurences.getFirst() + 1 > occ2.Occurences.getFirst()) {
					occ2.Occurences.removeFirst();
				} else {
					occ1.Occurences.removeFirst();
				}
			}
		}
		return res;
	}
}
